package cn.edu.zjut.mina.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.mina.core.session.IoSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import cn.edu.zjut.mina.bean.Card;
import cn.edu.zjut.mina.bean.RoomInfo;
import cn.edu.zjut.mina.bean.StandardFormat;
import cn.edu.zjut.mina.bean.UserSession;
import cn.edu.zjut.mina.interf.IRoomInfo;
import cn.edu.zjut.mina.po.EveryGameResult;
import cn.edu.zjut.mina.po.PlayerBattleInfo;
import cn.edu.zjut.mina.po.UserInfo;
import cn.edu.zjut.mina.repository.UserInfoRepository;
import cn.edu.zjut.mina.service.IEveryGameBeginService;
import cn.edu.zjut.mina.service.IGameOverService;
import cn.edu.zjut.mina.service.INotificationService;
import cn.edu.zjut.mina.util.UserSessionMap;

@Service("everyGameBeginService")
public class EveryGameBeginServiceImpl implements IEveryGameBeginService {

	/**
	 * 用于存放用户信息的集合
	 */
	private final UserSessionMap userSessionMap = UserSessionMap.getInstance();
	
	@Qualifier("notificationService")
	@Autowired
	private INotificationService notificationService;
	
	@Qualifier("gameOverService")
	@Autowired
	private IGameOverService gameOverService;
	
	@Autowired
	private UserInfoRepository userInfoRepository;
	
	private Random random = new Random(System.currentTimeMillis());
	private final Card[] mCards = Card.mCards;
	private final int NUMBER_OF_CARDS = 5;//每人的牌数
	private int bankerNumber = 0;//庄家编号(从0开始)
	private IRoomInfo roomInfo;
	private List<UserSession> playerSessionList;
	
	public void start(StandardFormat inJson, IoSession session){
	
		roomInfo = userSessionMap.get(inJson.roomId);
		playerSessionList = roomInfo.getUserSessions();
		
		roomInfo.setActual_number_of_games(roomInfo.getActual_number_of_games() + 1);
		
		
		userSessionMap.get(inJson.roomId).setActualGameStart(true);
		//每次开始前重置玩家数据
		for (int i = 0; i < roomInfo.getParticipation(); i++) {
			playerSessionList.get(i).user.reSet();
		}
		disorganize(50);//打乱牌
		for(int i = 0; i < roomInfo.getParticipation(); i++) {//发牌
			Card[] mPlayerCards = new Card[NUMBER_OF_CARDS];
			for(int j = 0; j < NUMBER_OF_CARDS; j++) {
				mPlayerCards[j] = mCards[i * NUMBER_OF_CARDS + j];
			}
			playerSessionList.get(i).user.setCards(mPlayerCards);
		}
		
		for(int i = 0; i < roomInfo.getParticipation(); i++) {//获取牌信息
			playerSessionList.get(i).user.getConcreteCards();
		}
		
		notificationService.notificationDeal(inJson.roomId);//通知发牌
		
		bankerNumber = roomInfo.getBankerNumber();//获取庄家编号
		
		if (roomInfo.getLzxs() == 1) {//固定庄
			playerSessionList.get(bankerNumber).user.setBanker(true);//设置庄家
		} else {//破牛庄
			if (playerSessionList.get(bankerNumber).user.ismLastRoundPoNiu()) {//如果庄家上一局破牛
				bankerNumber = (bankerNumber + 1) % roomInfo.getParticipation();//庄家序号后移
				playerSessionList.get(bankerNumber).user.setBanker(true);//设置庄家
			} else {
				playerSessionList.get(bankerNumber).user.setBanker(true);//设置庄家
			}
		}
		roomInfo.setBankerNumber(bankerNumber);//设置庄家编号
		
		//System.out.println("这一局的庄家是" + bankerNumber + "号");
		
	}
	
	public void deal(StandardFormat inJson, IoSession session) {
		// TODO Auto-generated method stub
		System.out.println("execute --Deal()-- method.");
		
		roomInfo = userSessionMap.get(inJson.roomId);
		playerSessionList = roomInfo.getUserSessions();
		
		
		for (int i = 0; i < roomInfo.getParticipation(); i++) {
			System.out.println(i + ": ");
			playerSessionList.get(i).user.computeNiuNiu();
			if (playerSessionList.get(i).user.isHasNiuNiu()) {
				playerSessionList.get(i).user.setmLastRoundPoNiu(false);//有牛
				playerSessionList.get(i).user.computeResidueSum();
			} else {
				playerSessionList.get(i).user.setmLastRoundPoNiu(true);
				//System.out.println("玩家" + i + "破牛了");
			}
		}
		
		for (int i = 0; i < roomInfo.getParticipation(); i++) {//计算输赢
			if (playerSessionList.get(i).user.isBanker())
				continue;
			if (playerSessionList.get(i).user.isHasNiuNiu() 
					&& playerSessionList.get(bankerNumber).user.isHasNiuNiu()) { //都有牛的情况
				if (playerSessionList.get(i).user.isFiveTen() && !playerSessionList.get(bankerNumber).user.isFiveTen()) {
					//System.out.println("闲家 " + i + "赢5倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.FIVE_TIMES);
				} else if (!playerSessionList.get(i).user.isFiveTen() && playerSessionList.get(bankerNumber).user.isFiveTen()) {
					//System.out.println("庄家赢5倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_FIVE_TIMES);//庄家赢5倍就是闲家输5倍
				} else if (playerSessionList.get(i).user.isFiveTen() && playerSessionList.get(bankerNumber).user.isFiveTen()) {
					if (playerSessionList.get(i).user.getMaxCardsNum() > playerSessionList.get(bankerNumber).user.getMaxCardsNum()) {
						//System.out.println("闲家 " + i + "赢5倍");
						playerSessionList.get(i).user.setmWinRatio(WinBetRatio.FIVE_TIMES);
					} else if (playerSessionList.get(i).user.getMaxCardsNum() < playerSessionList.get(bankerNumber).user.getMaxCardsNum()) {
						//System.out.println("庄家赢5倍");
						playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_FIVE_TIMES);
					} else {
						if (playerSessionList.get(i).user.getMaxCardsColor() > playerSessionList.get(bankerNumber).user.getMaxCardsColor()) {
							//System.out.println("闲家 " + i + "赢5倍");
							playerSessionList.get(i).user.setmWinRatio(WinBetRatio.FIVE_TIMES);
						}
						else {
							//System.out.println("庄家赢5倍");
							playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_FIVE_TIMES);
						}
					}
				} else {
					if (playerSessionList.get(i).user.getResidueSum() % 10 == 0 && playerSessionList.get(bankerNumber).user.getResidueSum() % 10 != 0) {
						//System.out.println("闲家 " + i + "赢3倍");
						playerSessionList.get(i).user.setmWinRatio(WinBetRatio.THREE_TIMES);
					} else if (playerSessionList.get(i).user.getResidueSum() % 10 != 0 && playerSessionList.get(bankerNumber).user.getResidueSum() % 10 == 0) {
						//System.out.println("庄家赢3倍");
						playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_THREE_TIMES);
					} else if (playerSessionList.get(i).user.getResidueSum() % 10 == 0 && playerSessionList.get(bankerNumber).user.getResidueSum() % 10 == 0) {
						if (playerSessionList.get(i).user.getMaxCardsNum() > playerSessionList.get(bankerNumber).user.getMaxCardsNum()) {
							//System.out.println("闲家 " + i + "赢3倍");
							playerSessionList.get(i).user.setmWinRatio(WinBetRatio.THREE_TIMES);
						} else if (playerSessionList.get(i).user.getMaxCardsNum() < playerSessionList.get(bankerNumber).user.getMaxCardsNum()) {
							//System.out.println("庄家赢3倍");
							playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_THREE_TIMES);
						} else {
							if (playerSessionList.get(i).user.getMaxCardsColor() > playerSessionList.get(bankerNumber).user.getMaxCardsColor()) {
								//System.out.println("闲家 " + i + "赢3倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.THREE_TIMES);
							} else {
								//System.out.println("庄家赢3倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_THREE_TIMES);
							}
						}
					} else {
						if (playerSessionList.get(i).user.getResidueSum() % 10 > playerSessionList.get(bankerNumber).user.getResidueSum() % 10) {
							if (playerSessionList.get(i).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
								//System.out.println("闲家 " + i + "赢2倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.TWO_TIMES);
							} else {
								//System.out.println("闲家 " + i + "赢1倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.ONE_TIMES);
							}
						} else if (playerSessionList.get(i).user.getResidueSum() % 10 < playerSessionList.get(bankerNumber).user.getResidueSum() % 10) {
							if (playerSessionList.get(bankerNumber).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
								//System.out.println("庄家赢2倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_TWO_TIMES);
							} else {
								//System.out.println("庄家赢1倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_ONE_TIMES);
							}
						} else {
							if (playerSessionList.get(i).user.getMaxCardsNum() > playerSessionList.get(bankerNumber).user.getMaxCardsNum() && playerSessionList.get(i).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
								//System.out.println("闲家 " + i + "赢2倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.TWO_TIMES);
							} else if (playerSessionList.get(i).user.getMaxCardsNum() > playerSessionList.get(bankerNumber).user.getMaxCardsNum() && playerSessionList.get(i).user.getResidueSum() % 10 < roomInfo.getCriticalOfTwoTimes()) {
								//System.out.println("闲家 " + i + "赢1倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.ONE_TIMES);
							} else if (playerSessionList.get(i).user.getMaxCardsNum() < playerSessionList.get(bankerNumber).user.getMaxCardsNum() && playerSessionList.get(bankerNumber).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
								//System.out.println("庄家赢2倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_TWO_TIMES);
							} else if (playerSessionList.get(i).user.getMaxCardsNum() < playerSessionList.get(bankerNumber).user.getMaxCardsNum() && playerSessionList.get(bankerNumber).user.getResidueSum() % 10 < roomInfo.getCriticalOfTwoTimes()) {
								//System.out.println("庄家赢1倍");
								playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_ONE_TIMES);
							} else {
								if (playerSessionList.get(i).user.getMaxCardsColor() > playerSessionList.get(bankerNumber).user.getMaxCardsColor() && playerSessionList.get(i).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
									//System.out.println("闲家 " + i + "赢2倍");
									playerSessionList.get(i).user.setmWinRatio(WinBetRatio.TWO_TIMES);
								} else if (playerSessionList.get(i).user.getMaxCardsColor() > playerSessionList.get(bankerNumber).user.getMaxCardsColor() && playerSessionList.get(i).user.getResidueSum() % 10 < roomInfo.getCriticalOfTwoTimes()) {
									//System.out.println("闲家 " + i + "赢1倍");
									playerSessionList.get(i).user.setmWinRatio(WinBetRatio.ONE_TIMES);
								} else if (playerSessionList.get(i).user.getMaxCardsColor() < playerSessionList.get(bankerNumber).user.getMaxCardsColor() && playerSessionList.get(i).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
									//System.out.println("庄家赢2倍");
									playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_TWO_TIMES);
								} else {
									//System.out.println("庄家赢1倍");
									playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_ONE_TIMES);
								}
							}
						}
						
					}
				}
			} else if (playerSessionList.get(i).user.isHasNiuNiu() && !playerSessionList.get(bankerNumber).user.isHasNiuNiu()) { //闲家有牛的情况
				if (playerSessionList.get(i).user.isFiveTen()) {
					//System.out.println("闲家 " + i + "赢5倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.FIVE_TIMES);
				} else if (playerSessionList.get(i).user.getResidueSum() % 10 == 0) {
					//System.out.println("闲家 " + i + "赢3倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.THREE_TIMES);
				} else if (playerSessionList.get(i).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
					//System.out.println("闲家 " + i + "赢2倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.TWO_TIMES);
				} else {
					//System.out.println("闲家 " + i + "赢1倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.ONE_TIMES);
				}
			} else if (!playerSessionList.get(i).user.isHasNiuNiu() && playerSessionList.get(bankerNumber).user.isHasNiuNiu()) {//庄家有牛
				if (playerSessionList.get(bankerNumber).user.isFiveTen()) {
					//System.out.println("庄家赢5倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_FIVE_TIMES);
				} else if (playerSessionList.get(bankerNumber).user.getResidueSum() % 10 == 0) {
					//System.out.println("庄家赢3倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_THREE_TIMES);
				} else if (playerSessionList.get(bankerNumber).user.getResidueSum() % 10 >= roomInfo.getCriticalOfTwoTimes()) {
					//System.out.println("庄家赢2倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_TWO_TIMES);
				} else {
					//System.out.println("庄家赢1倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_ONE_TIMES);
				}
			} else {//都没有牛
				if (playerSessionList.get(i).user.getMaxCardsNum() > playerSessionList.get(bankerNumber).user.getMaxCardsNum()) {
					//System.out.println("闲家 " + i +"赢1倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.ONE_TIMES);
				} else if (playerSessionList.get(i).user.getMaxCardsNum() < playerSessionList.get(bankerNumber).user.getMaxCardsNum()) {
					//System.out.println("庄家赢1倍");
					playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_ONE_TIMES);
				} else {
					if (playerSessionList.get(i).user.getMaxCardsColor() > playerSessionList.get(bankerNumber).user.getMaxCardsColor()) {
						//System.out.println("闲家赢1倍");
						playerSessionList.get(i).user.setmWinRatio(WinBetRatio.ONE_TIMES);
					} else if (playerSessionList.get(i).user.getMaxCardsColor() < playerSessionList.get(bankerNumber).user.getMaxCardsColor()) {
						//System.out.println("庄家赢1倍");
						playerSessionList.get(i).user.setmWinRatio(WinBetRatio.MINUS_ONE_TIMES);
					}
				}
			}
		}
		int mBankerJF = 0;//庄家的积分
		for (int i = 0; i < roomInfo.getParticipation(); i++) {
			if (playerSessionList.get(i).user.isBanker()) {
				for (int j = 0; j < roomInfo.getParticipation(); j++) {
					mBankerJF += roomInfo.getRatio() * playerSessionList.get(j).user.getmWinRatio();
				}
				mBankerJF = -mBankerJF;
				playerSessionList.get(i).user.setCredits(playerSessionList.get(i).user.getCredits() + mBankerJF);
				//System.out.println("庄家本局比赛积分 = " + mBankerJF);
			} else {
				playerSessionList.get(i).user.setCredits(playerSessionList.get(i).user.getCredits() + roomInfo.getRatio() * playerSessionList.get(i).user.getmWinRatio());
				//System.out.println("闲家" + i + "本局比赛积分 = " + roomInfo.getRatio() * playerSessionList.get(i).user.getmWinRatio() 
				//		+ "     下注倍率： " + roomInfo.getRatio() + "  赢得的倍率：" + playerSessionList.get(i).user.getmWinRatio());
			}
		}
		
		for (int i = 0; i < roomInfo.getParticipation(); i++) {
			if (playerSessionList.get(i).user.isBanker()) {
				System.out.println("庄家积分 = " + playerSessionList.get(i).user.getCredits());
			} else {
				//playerSessionList.get(i).user.setCredits(playerSessionList.get(i).user.getCredits() + roomInfo.getRatio() * playerSessionList.get(i).user.getmWinRatio());
				System.out.println("闲家" + i + "比赛积分 = " + playerSessionList.get(i).user.getCredits());
			}
		}
		
		
		
//		outJson.resultInfo = "成功";
//		outJson.result = true;
//		res.setResultCode(ProtocalRegulation.DEAL);
//		datas = GsonUtils.beanToJson(outJson).trim();
//		res.setContent(datas);


		
		
		System.out.println("第" + (roomInfo.getActual_number_of_games()) + "局结束");

		//该小局结束
		userSessionMap.get(inJson.roomId).setActualGameStart(false);
		
		EveryGameResult eveyGameResult = new EveryGameResult();
		eveyGameResult.setTotalGameResult(roomInfo.getTotalGameResult());
		List<PlayerBattleInfo> playerBattleInfos = new ArrayList<PlayerBattleInfo>();
		for (int i = 0; i < roomInfo.getActualParticipation(); i++) {
			PlayerBattleInfo playerBattleInfo = new PlayerBattleInfo();
			playerBattleInfo.setEveryGameResult(eveyGameResult);
			UserInfo user = roomInfo.getUserSessions().get(i).user;
			
			playerBattleInfo.setUserId(user.getUserId());
			int cardOne = (user.getCards()[0]).getColor() * 13 + (user.getCards()[0]).getNumber();
			playerBattleInfo.setCardone(cardOne);
			int cardTwo = (user.getCards()[1]).getColor() * 13 + (user.getCards()[1]).getNumber();
			playerBattleInfo.setCardtwo(cardTwo);
			int cardThree = (user.getCards()[2]).getColor() * 13 + (user.getCards()[2]).getNumber();
			playerBattleInfo.setCardthree(cardThree);
			int cardFour = (user.getCards()[3]).getColor() * 13 + (user.getCards()[3]).getNumber();
			playerBattleInfo.setCardfour(cardFour);
			int cardFive = (user.getCards()[4]).getColor() * 13 + (user.getCards()[4]).getNumber();
			playerBattleInfo.setCardfive(cardFive);
			
			playerBattleInfo.setCredit(user.getCredits());
			if (user.ismLastRoundPoNiu()) {
				playerBattleInfo.setYouNiu(0);
			} else 
				playerBattleInfo.setYouNiu(1);
			playerBattleInfos.add(playerBattleInfo);
		}
		eveyGameResult.setPlayerBattleInfos(playerBattleInfos);
		if (roomInfo.getTotalGameResult().getEveryGameResult() == null) {
			roomInfo.getTotalGameResult().setEveryGameResult(new ArrayList<EveryGameResult>());
		}
		
		roomInfo.getTotalGameResult().getEveryGameResult().add(eveyGameResult);
		
		/**
		 * 庄家不管掉线与否，都在这里扣房卡
		 */
		if (roomInfo.getActual_number_of_games() == 1) {//游戏开始过了就扣房卡
			UserInfo user = roomInfo.getUserSessions().get(0).user;//获取庄家
			user.setRoomCardNum(user.getRoomCardNum() - roomInfo.getDeductRoomCard());//扣除房卡
			//user.setLostConnection(0);
			userInfoRepository.save(user);
		}
		
		/**
		 * 下面是游戏结束的处理
		 */
		if (roomInfo.getActual_number_of_games() == roomInfo.getNumber_of_games()) {
			gameOverService.statisticalResult(roomInfo);
		}
		
	}
	
	/**
	 * 将牌打乱顺序
	 * @param num打乱的次数，num越大打乱的越好
	 */
	private void disorganize(int num) {
		for(int i = 0; i < num; i++) {
			int a = Math.abs(random.nextInt(52));
			int b = Math.abs(random.nextInt(52));
			Card c = mCards[a];
			mCards[a] = mCards[b];
			mCards[b] = c;
		}
	}
	
	//内部类区块
	class WinBetRatio {
		public static final int ONE_TIMES = 1;
		public static final int TWO_TIMES = 2;
		public static final int THREE_TIMES = 3;
		public static final int FIVE_TIMES = 5;
		
		public static final int MINUS_ONE_TIMES = -1;
		public static final int MINUS_TWO_TIMES = -2;
		public static final int MINUS_THREE_TIMES = -3;
		public static final int MINUS_FIVE_TIMES = -5;
	}

}
